package form.ui {
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import form.dispatchers.FormElementDispatcher;
	import form.events.DropDownButtonEvent;
	import form.events.FormElementEvent;
	import form.events.OptionEvent;
	import form.interfaces.IFormElement;
	import form.ui.component.Select.DropDown;
	import form.ui.component.Select.DropDownButton;
	import form.ui.component.Select.Option;
	import form.ui.component.Select.Option.SelectedOption;
	import form.ui.core.Frame;
	import form.ui.core.FMSprite;
	import form.ui.core.Stack;
	import form.utils.EventUtils;
	import form.utils.HierarchyUtils;
	
	public class Select extends FMSprite implements IFormElement {
		public static const DEFAULT_WIDTH:int = 140;
		public static const DEFAULT_HEIGHT:int = 20;
		
		private var selected:SelectedOption = new SelectedOption();
		private var button:DropDownButton = new DropDownButton();
		private var dropDown:DropDown;
		
		private var _formName:String;
		private var _formValue:String;
		
		public function Select() {
			super();
			
			this.dropDown = new DropDown(this);
		
			this.addChild(this.button);
			this.addChild(this.selected);
			
			this.addEventListener(DropDownButtonEvent.CLICKED, this.onDropDownButtonClicked);
			this.addEventListener(MouseEvent.ROLL_OUT, this.dropDown.onMouseOut);
			this.addEventListener(MouseEvent.ROLL_OVER, this.dropDown.onMouseOver);
			
			this.addEventListener(Event.ADDED_TO_STAGE, this.onAddedToStage);
			
			this.width = Select.DEFAULT_WIDTH;
			this.height = Select.DEFAULT_HEIGHT;
			
			this.enable();
			
			var e:FormElementEvent = new FormElementEvent(FormElementEvent.INITIALIZED);
			e.element = this;
			
			FormElementDispatcher.instance.dispatchEvent(e);
		}
		
		public function set formName(value:String):void {
			this._formName = value;
		}
		
		public function get formName():String {
			return this._formName;
		}
		
		public function set formValue(value:String):void {
			this._formValue = value;	
		}
		
		public function get formValue():String {
			return this._formValue;
		}
		
		public function enable():void {
			this.button.enable();
			this.selected.enable();
		}
		
		public function disable():void {
			if (this.dropDown.isOpen) {
				this.dropDown.close();
			}
			
			this.button.disable();
			this.selected.disable();
		}
		
		public override function set width(value:Number):void {
			super.width = value;
			
			this.position();
		}
		
		
		public override function set height(value:Number):void {
			super.height = value;
			
			this.position();
		}
		
		public function set maxDropDownHeight(value:int):void {
			this.dropDown.maxHeight = value;
		}
		public function get maxDropDownHeight():int { 
			return this.dropDown.maxHeight;
		} 
		
		public function addOption(text:String, value:String):void {
			dropDown.addOption(text, value);
		}
		
		public function addHeader(text:String):void {
			dropDown.addHeader(text);
		}
		
		public function addSeparator():void {
			dropDown.addSeparator();
		}
		
		public function selectOptionByText(text:String):void {
			var option:Option = this.dropDown.findOptionByText(text);
			if (option != null) { option.select(); }
		}
		
		public function selectOptionByValue(value:String):void {
			var option:Option = this.dropDown.findOptionByValue(value);
			if (option != null) { option.select(); }
		}
		
		public function showOptionByText(text:String):void {
			var option:Option = this.dropDown.findOptionByText(text);
			if (option != null) { option.show(); }
		}
		
		public function showOptionByValue(value:String):void {
			var option:Option = this.dropDown.findOptionByValue(value);
			if (option != null) { option.show(); }
		}
		
		public function clear():void {
			dropDown.clear();
		}
		
		public function set prompt(value:String):void {
			this.text = value;
			this.formValue = null;
			this.dropDown.unselectAllOptions();
		}
		
		public function set text(value:String):void {
			this.selected.text = value;
		}
		
		protected function position():void {
			this.button.coordinates = [0, 0];
			this.button.synchronizeWidth = this.width;
			this.button.synchronizeHeight = this.height;
			
			this.selected.coordinates = [0, 0];
			this.selected.dimensions = [this.width - DropDownButton.RIGHT_BUTTON_WIDTH, this.height];
		}
		
		protected function onAddedToStage(e:Event):void {
			this.position();
			
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDownOutside);
		}
		
		protected function onDropDownButtonClicked(e:Event):void {
			EventUtils.stopPropagation(e);
			
			if (this.dropDown.isOpen) {
				this.dropDown.close();
			} else {
				this.dropDown.open();
			}
		}
		
		protected function onMouseDownOutside(e:MouseEvent):void {
			if (e.target != null && e.target is DisplayObject && (
				e.target == this || HierarchyUtils.isAncestor(this, DisplayObject(e.target)) || 
				e.target == this.dropDown || HierarchyUtils.isAncestor(this.dropDown, DisplayObject(e.target))
			)) { return; }
			
			if (this.dropDown.isOpen) {
				this.dropDown.close();
			} 
		}
	}
}